﻿namespace AzureCamp.RSSAggregator_WorkerRole
{
    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.IO;
    using System.Linq;
    using System.Threading;
    using AzureCamp.RssAggregatorBusiness.Queue;
    using Microsoft.Samples.ServiceHosting.StorageClient;
    using Microsoft.ServiceHosting.ServiceRuntime;
    using AzureCamp.Table.RssAggregatorBusiness;
    using AzureCamp.RssAggregatorBusiness;
    
    public class WorkerRole : RoleEntryPoint
    {
        private static StorageAccountInfo accountTableInfo;
        private static BlobStorage blobStorage;
        private static QueueDeleteBlob queueDeleteBlob;

        private static Thread t1;
        private static Thread DeleteBlobThread;
        private static bool isInitialized;
        private static int numberOfPosts;
        private static int timeToSleep;

        public override bool Initialize()
        {
            isInitialized = false;
            blobStorage = BlobStorage.Create(StorageAccountInfo.GetDefaultBlobStorageAccountFromConfiguration());
            queueDeleteBlob = new QueueDeleteBlob();
            Int32.TryParse(RoleManager.GetConfigurationSetting("NumberOfPosts"), out numberOfPosts);
            Int32.TryParse(RoleManager.GetConfigurationSetting("TimeToSleep"), out timeToSleep);
            accountTableInfo = StorageAccountInfo.GetAccountInfoFromConfiguration("TableStorageEndpoint");
            TableStorage.CreateTablesFromModel(typeof(RSSAggregatorContext), accountTableInfo);

            t1 = new Thread(MainThread);
            
            
            isInitialized = base.Initialize();

            return isInitialized;
        }

        private static void DeleteBlobs()
        {
            IEnumerable<Message> messages = queueDeleteBlob.GetBlobsToDelete();
            foreach (Message m in messages)
            {
                string message = m.ContentAsString();
                RoleManager.WriteToLog("Information", "Request for delete received :" + message);
                string[] msg = message.Split(':');
                BlobContainer container = blobStorage.GetBlobContainer(msg[0]);
                bool isDeleted = container.DeleteBlob(msg[1]);
                RoleManager.WriteToLog("Information", "Delete blob " + message + ":" + isDeleted);
                DeleteBlobThread.Abort();
            }
        }

        public override void Start()
        {
            while (!isInitialized)
            {
            }
            t1.Start();
        }
        
        public override RoleStatus GetHealthStatus()
        {
            return RoleStatus.Healthy;
        }

        public static void DeleteOldBlobThread()
        {

        }

        public static void MainThread()
        {
            // This is a sample worker implementation. Replace with your logic.
            RoleManager.WriteToLog("Information", "Main Thread entry point called");
            int iteration = 0;
            
            while (true)
            {
                SleepRandom();
                DeleteBlobThread = new Thread(DeleteBlobs);
                DeleteBlobThread.Start();
                RoleManager.WriteToLog("Information", "Checking for feeds to update");
                
                
                IEnumerable<Feed> feeds;
                var context = new RSSAggregatorContext(accountTableInfo);
                context.MergeOption = System.Data.Services.Client.MergeOption.OverwriteChanges;

                do
                {
                    feeds = context.GetFeedToUpdate(1,1);
                    if (feeds != null)
                    {
                        RoleManager.WriteToLog("Information", "Updating  : " + feeds.Count() + " feeds");
                        RoleManager.WriteToLog("Information", "Iteration : " + iteration++);
                        foreach (Feed f in feeds)
                        {

                            //mise a jour du feed
                            context.UpdatedFeed(f);
                            RoleManager.WriteToLog("Information", "Updating " + (f).Title + " feed");
                            RoleManager.WriteToLog("Information", "Number of feeds : " + (f).GetUrls().Count);
                            //mise a jour du blob
                            SaveRssInBlob(f);
                        }
                    }
                } while (feeds != null);
                context = null;
                Thread.Sleep(timeToSleep * 60 * 1000);
            }
        }
        
        private static BlobContainer GetContainer(string containerName)
        {
            
            //BlobContainer newContainer = blobStorage.GetBlobContainer(RoleManager.GetConfigurationSetting("ContainerName"));
            BlobContainer newContainer = blobStorage.GetBlobContainer(containerName);
            newContainer.CreateContainer(null, ContainerAccessControl.Public);
            return newContainer;
        }
        
        public static void SaveRssInBlob(Feed rss)
        {
            NameValueCollection metadata = new NameValueCollection();
            metadata["Id"] = rss.Title;
            metadata["Filename"] = String.Format("{0}-{1}.xml", rss.Title, DateTime.Now.ToShortDateString().Replace('/', '-'));
            metadata["Date"] = DateTime.Now.ToString();

            BlobProperties properties = new BlobProperties(rss.Title);
            properties.ContentType = "text/xml";
            properties.Metadata = metadata;
            
            ILocalResource myIO = RoleManager.GetLocalResource("rssrepository");
            string pathToFile = Path.Combine(myIO.RootPath, metadata["Filename"]);

            Stream s = rss.GetAgregatorAsStream(pathToFile, numberOfPosts);
            //Stream s = rss.GetAgregatorAsStream(numberOfPosts);
            BlobContents contents = new BlobContents(s);
            GetContainer(rss.Category).CreateBlob(properties, contents, true);
            s.Close();
        }

        public static void SleepRandom()
        {
            Random rnd = new Random();
            int random = rnd.Next(100);

            RoleManager.WriteToLog("Information", "Role will sleep for " + random / 10 + " seconds");
            Thread.Sleep(random * 100);
        }
    }
}
